package org.huoran.sakamichi.main.netty.webSocket;


import com.alibaba.fastjson.JSONObject;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.concurrent.GlobalEventExecutor;
import org.huoran.sakamichi.main.netty.webSocket.bean.MessageContent;
import org.huoran.sakamichi.main.netty.webSocket.bean.MessageDto;
import org.huoran.sakamichi.main.netty.webSocket.bean.MessageType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class TextWebSocketFrameHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    final Logger logger = LoggerFactory.getLogger(TextWebSocketFrameHandler.class);

    private static ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

    public static ChannelGroup getChannels(){
        return channels;
    }

    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        channels.add(ctx.channel());
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {}

    @Override
    protected void channelRead0(ChannelHandlerContext ctx,
                                TextWebSocketFrame msg) throws Exception {
        Channel incoming = ctx.channel();
        String location = incoming.remoteAddress().toString();
        String name = ClientManager.getInstance().getNameByLocation(location);
        MessageContent messageContent = new MessageContent();
        messageContent.setFrom(name);
        messageContent.setBody(msg.text());
        MessageDto messageDto = new MessageDto();
        messageDto.setContent(messageContent);
        for (Channel channel : channels) {
            if (channel != incoming){
                messageDto.setType(MessageType.MESSAGE_OTHERS);
            } else {
                messageDto.setType(MessageType.MESSAGE_OWN);
            }
            channel.writeAndFlush(new TextWebSocketFrame(JSONObject.toJSONString(messageDto)));
        }
    }

    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        Channel incoming = ctx.channel();
        String name = ClientManager.getInstance().getNameByLocation(incoming.remoteAddress().toString());
        MessageContent messageContent = new MessageContent();
        messageContent.setFrom(name);
        MessageDto messageDto = new MessageDto();
        messageDto.setContent(messageContent);
        messageDto.setType(MessageType.MEMBER_LEAVE);
        for (Channel channel : channels) {
            channel.writeAndFlush(new TextWebSocketFrame(JSONObject.toJSONString(messageDto)));
        }
        channels.remove(ctx.channel());
        ClientManager.getInstance().remove(incoming.remoteAddress().toString());
        logger.info("websocket client removed : " + incoming.remoteAddress() + " / " + name);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        Channel incoming = ctx.channel();
        String name = ClientManager.getInstance().getNameByLocation(incoming.remoteAddress().toString());
        logger.info("websocket client Inactive : " + incoming.remoteAddress() + " / " + name);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
            throws Exception {
        Channel incoming = ctx.channel();
        String name = ClientManager.getInstance().getNameByLocation(incoming.remoteAddress().toString());
        logger.info("websocket client exception : " + incoming.remoteAddress() + " / " + name);
        cause.printStackTrace();
        ctx.close();
    }

}
